package com.cym.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.cym.config.HomeConfig;
import com.cym.consts.FileConst;
import com.cym.model.Www;
import com.cym.model.WwwBak;
import com.cym.model.dto.ZipCheckDTO;
import com.cym.sqlhelper.bean.Page;
import com.cym.sqlhelper.bean.Sort;
import com.cym.sqlhelper.utils.ConditionOrWrapper;
import com.cym.sqlhelper.utils.SqlHelper;
import org.noear.solon.annotation.Inject;
import org.noear.solon.aspect.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class WwwService {

    private static final Logger logger = LoggerFactory.getLogger(WwwService.class);

    @Inject
    SqlHelper sqlHelper;

    @Inject
    HomeConfig homeConfig;

    /**
     * 检查压缩包
     * 新增是否存在通目录
     * 是否存在非法文件
     */
    public ZipCheckDTO check(Www www, String zipName, String zipTemp, String tempDir, String time) {
        ZipCheckDTO checkDTO = new ZipCheckDTO();
        checkDTO.setPass(true);
        String errorMsg = null;
        // 先解压到临时目录，判断zip文件是否重复，并且可以检查文件安全
        ZipUtil.unzip(zipTemp, tempDir);
        // 检查文件清单
        List<File> files = FileUtil.loopFiles(tempDir);
        AtomicBoolean safe = new AtomicBoolean(true);
        files.forEach(f -> {
            logger.debug("压缩包 [{}] 文件清单：{}", zipName, f.getPath().substring(f.getPath().lastIndexOf(time) + time.length() + 1));
            if (FileConst.DENY_TYPES.contains(FileUtil.getSuffix(f))) {
                logger.debug("非法文件：{}", f.getName());
                safe.set(false);
            }
        });
        if (!safe.get()) {
            errorMsg = "安全检查不通过，存在非法文件";
            checkDTO.setPass(false);
        } else {
            String rootPath;
            if (files.size() > 0) {
                // 提取网站根目录
                rootPath = files.get(0).getParent();
                rootPath = rootPath.substring(rootPath.lastIndexOf(time) + time.length() + 1);
                // 检查是否已存在同名目录
                String checkPath = www.getDir() + rootPath;
                if (StrUtil.isEmpty(www.getId()) && FileUtil.exist(checkPath)) {
                    errorMsg = "目录已存在 【" + checkPath + "】";
                    checkDTO.setPass(false);
                }
                checkDTO.setRootPath(rootPath);
            } else {
                errorMsg = "压缩包为空";
                checkDTO.setPass(false);
            }
        }
        checkDTO.setErrorMsg(errorMsg);
        return checkDTO;
    }

    /**
     * 备份 www
     * @param id id
     */
    public void backup(String id) {
        if (!StrUtil.isEmpty(id)) {
            WwwBak bak = new WwwBak();
            bak.setWwwId(id);
            // 备份路径
            String backDir = homeConfig.home + "wwwBack/" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "/";
            if (!FileUtil.exist(backDir)) {
                FileUtil.mkdir(backDir);
            }
            Www www = sqlHelper.findById(id, Www.class);
            backDir = backDir + www.getZipName();
            String wwwDir = www.getIndexDir();
            File zip = ZipUtil.zip(wwwDir, backDir, true);
            bak.setBackDir(zip.getPath());
            sqlHelper.insert(bak);
            // 备份完删除原目录
            FileUtil.del(www.getIndexDir());
        }
    }

    /**
     * www备份 分页查询
     */
    public Page search(Page page) {
        ConditionOrWrapper conditionOrWrapper = new ConditionOrWrapper();
        Sort sort = new Sort().add("createTime", Sort.Direction.DESC);
        page = sqlHelper.findPage(conditionOrWrapper, sort, page, WwwBak.class);
        return page;
    }

    /**
     * 备份还原
     * @param id id
     */
    public void restore(String id) {
        WwwBak bak = sqlHelper.findById(id, WwwBak.class);
        Www www = sqlHelper.findById(bak.getWwwId(), Www.class);
        // 备份完删除原目录
        FileUtil.del(www.getIndexDir());
        FileUtil.mkdir(www.getIndexDir());
        ZipUtil.unzip(bak.getBackDir(), www.getIndexDir().substring(0, www.getIndexDir().lastIndexOf("/")));
    }
}
